一上来便是一张天真无邪的笑脸

无头绪,f12查源码,发现source.php
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 
 | <?phphighlight_file(__FILE__);
 class emmm
 {
 public static function checkFile(&$page)
 {
 $whitelist = ["source"=>"source.php","hint"=>"hint.php"];
 if (! isset($page) || !is_string($page)) {
 echo "you can't see it";
 return false;
 }
 
 if (in_array($page, $whitelist)) {
 return true;
 }
 
 $_page = mb_substr(
 $page,
 0,
 mb_strpos($page . '?', '?')
 );
 if (in_array($_page, $whitelist)) {
 return true;
 }
 
 $_page = urldecode($page);
 $_page = mb_substr(
 $_page,
 0,
 mb_strpos($_page . '?', '?')
 );
 if (in_array($_page, $whitelist)) {
 return true;
 }
 echo "you can't see it";
 return false;
 }
 }
 
 if (! empty($_REQUEST['file'])
 && is_string($_REQUEST['file'])
 && emmm::checkFile($_REQUEST['file'])
 ) {
 include $_REQUEST['file'];
 exit;
 } else {
 echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
 }
 ?>
 
 | 
开始代码审计
网页通过对传入的参数进行过滤后进行文件包含
一开始我以为是需要满足所有的条件,但根据下文包含文件的代码发现只需要满足其中一个就足够了
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | if (! empty($_REQUEST['file'])&& is_string($_REQUEST['file'])
 && emmm::checkFile($_REQUEST['file'])
 ) {
 include $_REQUEST['file'];
 exit;
 } else {
 echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
 }
 
 | 
在尝试了许久之后我发现重点在于最后一个判断,即从解码函数开始的判断;在解码之后出现了新的变量$_page,然后对该变量进行分割,取出变量中问号之前的部分,覆盖原来的变量,再判断该变量是否位于白名单内。
| 12
 3
 4
 5
 6
 7
 
 | $_page = mb_substr($_page,
 0,
 mb_strpos($_page . '?', '?')
 );
 if (in_array($_page, $whitelist)) {
 return true;
 
 | 
判断通过后对文件进行包含,这时遍历文件目录就能找到flag了,文件名称在hint.php里
最终payload:
